package com.juice.iot.sdk;

import com.alibaba.fastjson.JSON;
import com.juice.iot.sdk.handler.PropGetHandler;
import com.juice.iot.sdk.handler.PropSetHandler;
import com.juice.iot.sdk.listener.PropGetListener;
import com.juice.iot.sdk.listener.PropSetListener;
import com.juice.iot.sdk.mqtt.MqttFactory;
import com.juice.iot.sdk.protocol.PropMessage;
import com.juice.iot.sdk.protocol.SysInfo;
import com.juice.iot.sdk.protocol.SysMsg;
import com.juice.iot.sdk.util.ShellUtils;
import com.juice.iot.sdk.util.SysUtil;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.UUID;

/**
 * Created by haonan on 2018/12/26
 */
public class JuiceClient {
    private final static Logger log = LoggerFactory.getLogger(JuiceClient.class);
    private String url;
    private String productCode;
    private String deviceCode;
    private String secret;
    private MqttClient mqttClient;
    private Map<String,PropGetHandler> propGetHandlerMap;
    private Map<String,PropSetHandler> propSetHandlerMap;

    private final static String DEFAULT_PRODUCT_CODE = "raspberry";
    private final static String DEFAULT_MQTT_URL = "tcp://www.guozhiyun.cn:2883";

    //prop属性get主题 /{product_code}/{device_code}/prop/get
    private String propGetTopic;
    private String propGetReplyTopic;

    //prop属性set主题 /{product_code}/{device_code}/prop/set
    private String propSetTopic;
    private String propSetReplyTopic;

    //prop属性report主题 /{product_code}/{device_code}/prop/report
    private String propReportTopic;

    //系统信息主体 /{product_code}/{device_code}/sys/up
    private String sysTopic;

    public static class Builder{
        //云端mqtt地址
        private String url = DEFAULT_MQTT_URL;
        //默认使用官方的产品模型
        private String productCode = DEFAULT_PRODUCT_CODE;
        //设备编码
        private String deviceCode;
        //设备秘钥
        private String secret;

        public Builder deviceCode(String deviceCode){
            this.deviceCode = deviceCode;
            return this;
        }

        public Builder deviceSecret(String secret){
            this.secret = secret;
            return this;
        }

        public Builder remote(String url){
            this.url = url;
            return this;
        }

        public Builder productCode(String productCode){
            this.productCode = productCode;
            return this;
        }

       public JuiceClient build() {
            return new JuiceClient(this);
        }
    }

    private JuiceClient(Builder builder) {
        this.url = builder.url;
        this.productCode = builder.productCode;
        this.deviceCode = builder.deviceCode;
        this.secret = builder.secret;
    }

    private void initTopics(){
        propGetTopic = "/"+productCode+"/"+deviceCode+"/prop/get";
        propGetReplyTopic  = "/"+productCode+"/"+deviceCode+"/prop/get_reply";
        propSetTopic = "/"+productCode+"/"+deviceCode+"/prop/set";
        propSetReplyTopic  = "/"+productCode+"/"+deviceCode+"/prop/set_reply";
        propReportTopic = "/"+productCode+"/"+deviceCode+"/prop/report";
        sysTopic = "/"+productCode+"/"+deviceCode+"/sys/up";
    }

    public void init(){

        initTopics();

        try {
            this.mqttClient = new MqttFactory().getMqttClient(url,deviceCode,secret);
            if(mqttClient.isConnected()){
                log.info("subscribe topic -> \n{} \n{}",propGetTopic,propSetTopic);
                //订阅属性get set
                mqttClient.subscribe(propGetTopic,new PropGetListener(this,propGetHandlerMap));
                mqttClient.subscribe(propSetTopic,new PropSetListener(propSetHandlerMap));

                //发送系统信息
                pushSysInfo();

                log.info(" start successful");
            }else{
                log.error(" connect to mqtt fail");
            }
        } catch (MqttException e) {
            log.error(" connect to mqtt error",e);
            System.exit(-1);
        }
    }

    /**
     * 上报属性消息
     */
    public void propGetReply(PropMessage propMessage) throws MqttException {
        String msg = JSON.toJSONString(propMessage);
        mqttClient.publish(propGetReplyTopic,msg.getBytes(),1,false);
    }

    public void setPropGetHandlerMap(Map<String, PropGetHandler> propGetHandlerMap) {
        this.propGetHandlerMap = propGetHandlerMap;
    }

    public void setPropSetHandlerMap(Map<String, PropSetHandler> propSetHandlerMap) {
        this.propSetHandlerMap = propSetHandlerMap;
    }

    /**
     * 发送系统信息
     * @throws MqttException
     */
    private void pushSysInfo() throws MqttException {
        SysMsg<SysInfo> sysMsg = new SysMsg<>();
        sysMsg.setId(UUID.randomUUID().toString());
        sysMsg.setType("sys_info");
        String revision = SysUtil.getRevision();
        String sn = SysUtil.getSn();
        SysInfo sysInfo = new SysInfo(revision,sn);
        sysMsg.setData(sysInfo);
        MqttMessage mqttMessage = new MqttMessage();
        mqttMessage.setPayload(JSON.toJSONString(sysMsg).getBytes());
        mqttClient.publish(sysTopic,mqttMessage);
        log.info("publish sys info -> {}:{}",sysTopic,mqttMessage);
    }



}
